﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing.Design;
using EnvDTE;
using System.ComponentModel;
using System.Windows.Forms;
using System.Reflection;

namespace SPVisualDev.VSAddin.Dialogs.PropertySheets
{
    internal class EventClassSelector : UITypeEditor
    {
        private ProjectItem m_feature_folder;

        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
        {
            return UITypeEditorEditStyle.Modal;
        }

        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            try
            {

                IPropertySheet sheet = context.Instance as IPropertySheet;
                m_feature_folder = sheet.ParentFeatureFolder;

                PropertyInfo piOwnerGrid = context.GetType().GetProperty("OwnerGrid");
                PropertyGrid grid = piOwnerGrid.GetValue(context, null) as PropertyGrid;
                DialogFeatureEditor featureEditor = grid.ParentForm as DialogFeatureEditor;

                if (!Common.HasAssemblyReferenced(m_feature_folder.ContainingProject, "Microsoft.Sharepoint"))
                {
                    string msg = "You need to add a reference to Microsoft.Sharepoint.dll in order to add event receivers to this project. If you are connected to a remote server, you can import this dll by right clicking on the project node in the solution explorer and choose 'Import SP dlls' from the context menu.";
                    MessageBox.Show(msg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

                    return value;
                }

                bool bMustBuild = false;

                if (string.IsNullOrEmpty(featureEditor.FeatureManager.AssemblyStrongName))
                    bMustBuild = true;
            
                bool hasKeyFile = Common.ProjectHasKeyFileAssigned(m_feature_folder.ContainingProject);
                if (!hasKeyFile)
                {
                    string msg = "You need to assign a key pair file to the project so it can be signed and have a valid strong name. Click OK if you want to import an existing or create a new.";

                    DialogResult result = MessageBox.Show(msg, "Prompt", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
                    if (result != DialogResult.OK)
                        return value;

                    using (DialogSNKSelector dialog = new DialogSNKSelector(m_feature_folder.ContainingProject))
                    {
                        result = dialog.ShowDialog();
                        if (result != DialogResult.OK)
                            return value;

                        if (dialog.ProjectExplorer.TreeView.SelectedNode == null ||
                            dialog.ProjectExplorer.TreeView.SelectedNode.Tag == null)
                            throw new Exception("No key file selected.");

                        ProjectItem key_item = dialog.ProjectExplorer.TreeView.SelectedNode.Tag as ProjectItem;
                        if (key_item == null)
                            throw new Exception("No key file selected.");

                        if (key_item.Kind != Constants.vsProjectItemKindPhysicalFile)
                            throw new Exception("No key file selected.");

                        key_item.ContainingProject.Properties.Item("AssemblyOriginatorKeyFile").Value = Common.GetProjectItemPath(key_item);
                        key_item.ContainingProject.Properties.Item("SignAssembly").Value = true;
                        key_item.ContainingProject.Properties.Item("AssemblyOriginatorKeyFileType").Value = 1;


                        Common.SetProjectGlobalConfigKey(key_item.ContainingProject, "AssemblyBuildType", "GAC", true);

                        bool isProjectUnderSCC = key_item.DTE.SourceControl.IsItemUnderSCC(key_item.ContainingProject.FullName);
                        if (isProjectUnderSCC)
                        {
                            bool isProjectCheckedOut = key_item.DTE.SourceControl.IsItemCheckedOut(key_item.ContainingProject.FullName);
                            if (!isProjectCheckedOut)
                                key_item.DTE.SourceControl.CheckOutItem(key_item.ContainingProject.FullName);
                        }

                        key_item.ContainingProject.Save(key_item.ContainingProject.FullName);
                    }

                    bMustBuild = true;
                }

                if (bMustBuild)
                {
                    MessageBox.Show("SPVisualDev must build the project now to be able to extract the public key token. Click OK to proceed.", "Prompt", MessageBoxButtons.OK, MessageBoxIcon.Information);

                    bool b = Common.BuildProject(m_feature_folder.ContainingProject, true, true);
                    if (!b)
                    {
                        throw new Exception("Build failed. See the build output window for more details.");
                    }
                }

                using (DialogCodeFileSelector dialog = new DialogCodeFileSelector(m_feature_folder.ContainingProject, featureEditor.DefaultCodeNamespace))
                {

                    Project project = m_feature_folder.ContainingProject;

                    if (featureEditor.DefaultCodeFolder.StartsWith("<Feature folder>\\", StringComparison.OrdinalIgnoreCase))
                    {
                        dialog.StartupFolder = Common.GetProjectItemPath(sheet.ParentFeatureFolder, true) + "\\CodeFiles";
                    }
                    else
                    {
                        dialog.StartupFolder = featureEditor.DefaultCodeFolder.Replace("<Project root>\\", "");
                    }

                    dialog.Text = "Choose an event receiver class";


                    DialogResult result = dialog.ShowDialog();
                    if (result != DialogResult.OK)
                        return value;

                    if (dialog.SelectedCodeClass == null)
                    {
                        throw new Exception("No class selected.");
                    }

                    if (context.PropertyDescriptor.PropertyType == typeof(CodeClass))
                    {
                        return dialog.SelectedCodeClass;
                    }
                    else
                    {
                        return dialog.SelectedCodeClass.FullName;
                    }
                }

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex);
            }

            return value;

        }

    }

}
